#include <math.h>
#include "glisomath.h"

void GlIsoMath::TileToScreen(GlFixed tileX, GlFixed tileY, GlFixed tileZ,
							int tileWidth, int tileHeight,
							int screenToOffsetX, int screenToOffsetY,
							GlFixed* screenX, GlFixed* screenY)
{
	GlFixed vX = tileX * GlFixed(tileWidth / 2)
				- tileY * GlFixed(tileWidth / 2);
				
	GlFixed vY = tileX * GlFixed(tileHeight / 2)
				+ tileY * GlFixed(tileHeight / 2)
				+ tileZ * GlFixed(tileHeight);
				
	*screenX = vX + screenOffsetX;
	*screenY = -vY + screenOffsetY;
}

void GlIsoMath::ScreenToFlatTile(GlFixed screenX, GlFixed screenY, GlFixed tileZ,
								int tileWidth, in tileHeight,
								int screenOffsetX, int screenOffsetY,
								GlFixed* tileX, GlFixed* tileY)
{
	GlFixed vX = screenX - screenOffsetX;
	GlFixed vY = -screenY + screenOffsetY;
	
	*tileX = (vX / tileWidth) + (vY / tileHeight) - tileZ;
	*tileY = -(vX / tileWidth) + (vY / tileHeight) - tileZ;
}

void GlIsoMath::TileToWorld(GlFixed tileX, GlFixed tileY, GlFixed tileZ,
							GlFixed* worldX, GlFixed* worldY, GlFixed* worldZ)
{
	GlFixed csAlpha(0.7071067811865475244008443621045);
	
	*worldX = csAlpha * tileX - csAlpha * tileY;
	*worldY = csAlpha * tileX + csAlpha * tileY;
	*worldZ = tileZ;
}

GlIsoMath::GlIsoMath(int _tileWidth, int _tileHeight)
{
	tileWidth = _tileWidth;
	tileHeight = _tileHeight;
	screenOffsetX = 0;
	screenOffsetY = 0;
}

void GlIsoMath::SetScreenBaseToOrigin(int screenW, int screenH)
{
	screenOffsetX = screenW / 2;
	screenOffsetY = screenH;
}

void GlIsoMath::SetScreenCenterToTile(int screenW, int screenH, int tileX, int tileY, int tileZ)
{
	GlFixed sx;
	GlFixed sy;
	
	TileToScreen(tileX, tileY, tileZ,
				tileWidth, tileHeight,
				0, 0,
				&sx, &sy);
				
	screenOffsetX = screenW / 2 - sx.ToInt();
	screenOffsetY = screenH / 2 - sy.ToInt();
}

void GlIsoMath::SetScreenToTile(int screenX, int screenY,
								int tileX, int tileY, int tileZ)
{
	GlFixed sx;
	GlFixed sy;
	
	TileToScreen(tileX, tileY, tileZ,
				tileWidth, tileHeight,
				0, 0,
				&sx, &sy);
	screenOffsetX = screenX - sx.ToInt();
	screenOffsetY = screenY - sy.ToInt();
}

void GlIsoMath::TileToScreen(GlFixed tileX, GlFixed tileY, GlFixed tileZ,
							int* screenX, int* screenY) const
{
	GlFixed sx, sy;

	TileToScreen(	tileX, tileY, tileZ,
					tileWidth, tileHeight,
					screenOffsetX, screenOffsetY, 
					&sx, &sy );
	*screenX = sx.ToInt();
	*screenY = sy.ToInt();
}

void GlIsoMath::ScreenToFlatTile(int screenX, int screenY, GlFixed tileZ,
								GlFixed* mapX, GlFixed* mapY) const
{
	ScreenToFlatTile(screenX, screenY, tileZ,
					tileWidth, tileHeight,
					screenOffsetX, screenOffsetY,
					mapX, mapY);
}
